﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using TestesFixacao.Dominio.Modelos;

namespace TestesFixacao.Dominio.Repositorios.ADO
{
    public class RepositorioAdoMateria : IRepositorioMateria
    {
        #region querys

        private const string SqlInsereMateria =
            @"INSERT INTO [TestesFx].[dbo].[TBMateria]
           ([nome]
           ,[numeroDisciplina]
           ,[numeroSerie])
            VALUES
           ({0}nome,
           {0}numeroDisciplina,
           {0}numeroSerie)";

        private const string SqlEditaMateria =
            @"UPDATE [TBMateria]
                SET [nome]={0}nome
                WHERE [numero]={0}numero";

        private const string SqlExcluiMateria =
           @"DELETE FROM [TBMateria]
                WHERE [numero]={0}numero";

        private const string SqlSelecionaTodasMaterias =
           @"SELECT M.NUMERO AS NUMEROMATERIA,
		            M.NOME AS NOMEMATERIA,
		            D.NUMERO AS NUMERODISCIPLINA,
		            D.NOME AS NOMEDISCIPLINA,
		            S.NUMERO AS NUMEROSERIE,
		            S.DESCRICAO AS DESCRICAOSERIE
            FROM    [TBMATERIA] M INNER JOIN [TBDISCIPLINA] D
		            ON M.NUMERODISCIPLINA = D.NUMERO INNER JOIN
		            [TBSERIE] S ON M.NUMEROSERIE = S.NUMERO";

        private const string SqlSelecionaMateriaPorNumero =
           @"SELECT M.NUMERO AS NUMEROMATERIA,
		            M.NOME AS NOMEMATERIA,
		            D.NUMERO AS NUMERODISCIPLINA,
		            D.NOME AS NOMEDISCIPLINA,
		            S.NUMERO AS NUMEROSERIE,
                    S.DESCRICAO AS DESCRICAOSERIE
            FROM    [TBMATERIA] M INNER JOIN [TBDISCIPLINA] D
		            ON M.NUMERODISCIPLINA = D.NUMERO INNER JOIN
		            [TBSERIE] S ON M.NUMEROSERIE = S.NUMERO
            WHERE M.NUMERO= {0}NUMERO";

        private const string SqlSelecionaTodosPorDisciplina =
           @"SELECT M.NUMERO,
                    M.NOME,
                    M.NUMERODISCIPLINA,
                    S.NUMERO AS NUMEROSERIE,
                    S.DESCRICAO AS DESCRICAOSERIE
                FROM TBMATERIA AS M INNER JOIN TBSERIE AS S
                    ON M.NUMEROSERIE = S.NUMERO
                WHERE NUMERODISCIPLINA = {0}NUMERODISCIPLINA";

        private const string SqlSelecionaTodosPorMateria = @"
                            SELECT     TBQuestao.numero, TBQuestao.bimestre, TBQuestao.enunciado
                            FROM         TBQuestao INNER JOIN
                                    TBMateria ON TBQuestao.numeroMateria = TBMateria.numero
                            WHERE TBQuestao.numeroMateria = {0}numeroMateria";

        #endregion querys

        public void Adiciona(Materia materia)
        {
            materia.Numero = Db.Insert(SqlInsereMateria, GetParametros(materia));
        }

        public void Edita(Materia materia)
        {
            Db.Update(SqlEditaMateria, GetParametros(materia));
        }

        public void Exclui(Materia materia)
        {
            try
            {
                Db.Delete(SqlExcluiMateria, new object[] { "Numero", materia.Numero });
            }
            catch (Exception e)
            {
                throw new Exception("A materia não pode ser excluida pois está relacionada a um Disciplina.", e);
            }
        }

        public Materia SelecionaPorId(int id)
        {
            Materia materia = Db.Get(SqlSelecionaMateriaPorNumero, RowMapper,
                new object[] { "numero", id });

            return materia;
        }

        public List<Materia> SelecionaTodos()
        {
            return Db.GetAll<Materia>(SqlSelecionaTodasMaterias, RowMapper);
        }

        public List<Materia> SelecionaTodosPorDisciplina(Disciplina disciplina)
        {
            return Db.GetAll<Materia>(SqlSelecionaTodosPorDisciplina,
                Converter, new object[] { "numeroDisciplina", disciplina.Numero });
        }

        private Materia Converter(IDataReader reader)
        {
            Materia materia = new Materia();
            materia.Numero = Convert.ToInt32(reader["numero"]);
            materia.Nome = Convert.ToString(reader["nome"]);

            Serie serie = new Serie();
            serie.Numero = Convert.ToInt32(reader["numeroSerie"]);
            serie.Descricao = Convert.ToString(reader["descricaoSerie"]);

            materia.Serie = serie;
            return materia;
        }

        private Materia RowMapper(IDataReader reader)
        {
            Materia materia = new Materia();
            materia.Numero = Convert.ToInt32(reader["numeroMateria"]);
            materia.Nome = Convert.ToString(reader["nomeMateria"]);

            Serie serie = new Serie();
            serie.Numero = Convert.ToInt32(reader["numeroSerie"]);
            serie.Descricao = Convert.ToString(reader["descricaoSerie"]);

            materia.Serie = serie;

            materia.Disciplina = new Disciplina();
            materia.Disciplina.Nome = Convert.ToString(reader["nomeDisciplina"]);
            materia.Disciplina.Numero = Convert.ToInt32(reader["numeroDisciplina"]);

            return materia;
        }

        private object[] GetParametros(Materia materia)
        {
            return new object[]
            {
                "nome", materia.Nome,
                "numeroDisciplina", materia.Disciplina.Numero,
                "numeroSerie", materia.Serie.Numero
            };
        }
    }
}